package com.yunxiao.cloud.mq.util;

import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.UUID;

/**
 * @description: 创建动态队列与交换机
 * 1、init
 * 2、send
 *
 * 3.messageListenerContainer
 * @author: yunxiao
 * @date: 2020/1/7 15:25
 * @version: V1.0
 **/
@Component
public class RabbitUtil {

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Resource
    private RabbitAdmin rabbitAdmin;

    @Autowired
    private SimpleMessageListenerContainer messageListenerContainer;



    public RabbitUtil(RabbitTemplate rabbitTemplate) {
        this.rabbitTemplate = rabbitTemplate;
    }

    /**
     * 初始化队列相关信息
     *
     * @param exchange     交换机
     * @param routingKey   路由键
     * @param queueName 队列名称
     * @param exchangeType ExchangeTypes
     * @return true 成功
     */
    public boolean init(String exchange, String routingKey, String queueName, String exchangeType) {
        Queue queue = createQueue(queueName);
        addQueue(queue);
        Binding binding = null;
        switch (exchangeType) {
            case ExchangeTypes.DIRECT:
                DirectExchange directExchange = createDirectExchange(exchange);
                addExchange(directExchange);
                binding = createDirectBinding(queue, directExchange, routingKey);
                break;
            case ExchangeTypes.FANOUT:
                FanoutExchange fanoutExchange = createFanoutExchange(exchange);
                addExchange(fanoutExchange);
                binding = createFanoutBinding(queue, fanoutExchange);
                break;
            case ExchangeTypes.TOPIC:
                TopicExchange topicExchange = createTopicExchange(exchange);
                addExchange(topicExchange);
                binding = createTopicBinding(queue, topicExchange, routingKey);
                break;
            default:
                directExchange = createDirectExchange(exchange);
                addExchange(directExchange);
                binding = createDirectBinding(queue, directExchange, routingKey);
                break;
        }

        addBinding(binding);
        messageListenerContainer.addQueueNames(queueName);
        return true;
    }

    /**
     * 发送消息
     * @param object     消息对象
     * @param exchange   交换机
     * @param routingKey 路由键  空表示广播模式
     */
    public void send(Object object, String exchange, String routingKey) {
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend(exchange, routingKey, object, correlationData);
    }



    /**
     * 创建Exchange
     *
     * @param exchange
     */
    private void addExchange(AbstractExchange exchange) {
        rabbitAdmin.declareExchange(exchange);
    }

    /**
     * 创建一个指定的Queue
     *
     * @param queue
     * @return queueName
     */
    private String addQueue(Queue queue) {
        return rabbitAdmin.declareQueue(queue);
    }

    private void addBinding(Binding binding) {
        rabbitAdmin.declareBinding(binding);
    }

    /**
     * 绑定一个队列到一个匹配型交换器使用一个routingKey direct
     *
     * @param queue
     * @param exchange
     * @param routingKey
     */
    private Binding createDirectBinding(Queue queue, DirectExchange exchange, String routingKey) {
        return BindingBuilder.bind(queue).to(exchange).with(routingKey);
    }

    private Binding createFanoutBinding(Queue queue, FanoutExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange);
    }

    private Binding createTopicBinding(Queue queue, TopicExchange exchange, String routingKey) {
        return BindingBuilder.bind(queue).to(exchange).with(routingKey);
    }

    /**
     * 创建不删除的队列
     * @param queueName
     * @return
     */
    private Queue createQueue(String queueName) {
        return QueueBuilder.durable(queueName).build();
    }


    private DirectExchange createDirectExchange(String exchangeName) {
        return new DirectExchange(exchangeName, true, false);
    }

    private FanoutExchange createFanoutExchange(String exchangeName) {
        return new FanoutExchange(exchangeName, true, false);
    }

    private TopicExchange createTopicExchange(String exchangeName) {
        return new TopicExchange(exchangeName, true, false);
    }

}
